{% extends "layout.html" %}
{% block head %}

<link href="{{ url_for('static', filename='css/jquery.multiselect.css') }}" rel="stylesheet" type="text/css"/>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/ui-lightness/jquery-ui.min.css" rel="stylesheet" type="text/css"/>

<link href="{{ url_for('static', filename='selectize/css/selectize.bootstrap3.css') }}" rel="stylesheet" data-theme="bootstrap3">
<link href="{{ url_for('static', filename='css/heatmap.css') }}" rel="stylesheet">

<!-- Bootstrap -->
<link href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">

<style>

#sidebar {
    float: left;
    width: 320px;
    padding: 10px 10px;
    background: #fff;
}

#content {
    height: 100%;
    background: #fff;
}

#chart {
}

#legend {
}

</style>

{% endblock %} <!-- block head -->

{% block body %}

<div id='sidebar'>
  <label for="select-study">Studies:</label>
  <select id="select-study" name="study[]" placeholder="Select a study..."></select>
  <label for="select-sample-set">Sample Sets:</label>
  <select id="select-sample-set" name="sampleset[]" placeholder="Select sample sets..."></select>
  <label for="search-transcript">Transcripts:</label>
  <select id="select-transcript" name="transcript[]" placeholder="Search for transcripts..."></select>
  <button id="save-svg">Save SVG</button>
  <button id="save-pdf">Save PDF</button>
  <button id="save-png">Save PNG</button>

  <label for="select-sample-set2">Sample Sets:</label>
  <select id="select-sample-set2" name="sampleset2[]" multiple="multiple">
  </select>
</div>


<div id="content">
  <div id="legend"></div>  
  <div id="chart"></div>
</div>

<!-- Hidden form to submit the SVG data to the server, which will convert it to SVG/PDF/PNG downloadable file.
     The form is populated and submitted by the JavaScript below. -->
<form id="svgform" method="post" action="{{ url_for('download_current_image') }}">
    <input type="hidden" id="output_format" name="output_format" value="">
    <input type="hidden" id="data" name="data" value="">
</form>

{% endblock %} <!-- block body -->

{% block scripts %}

<!-- JAVASCRIPT LIBRARIES -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="{{ url_for('static', filename='boostrap/js/bootstrap.min.js') }}"></script>
<script src="http://d3js.org/d3.v3.js"></script>
<script src="{{ url_for('static', filename='js/d3-tip.js') }}"></script>
<script src="{{ url_for('static', filename='selectize/js/standalone/selectize.js') }}"></script>
<script src="{{ url_for('static', filename='js/jquery.multiselect.min.js') }}"></script>

<script src="{{ url_for('static', filename='js/underscore-min.js') }}" type='text/javascript'></script>
<script src="{{ url_for('static', filename='js/backbone-min.js') }}" type='text/javascript'></script>

<script>

var Transcript = Backbone.Model.extent({
	 idAttribute: "_id",
	 
	 defaults: {
		 
	 },
	 
	 initialize: function() {
		 
	 },
	 
});



function SelectionView() {
    var self = this;
    // define the current user selection
    self.selectedStudy = null;
    self.sampleSets = [];
    self.transcripts = [];
    
    // Load initial studies from server and convert to Study instances, then populate studies
    $.ajax({
        url: "{{ url_for('request_studies') }}",
        type: 'post',
        contentType: "application/json",
        dataType: 'json',
        data: JSON.stringify({}),
        error: function() {
            console.log('error requesting studies');
        },
        success: function(response) {
            var mappedStudies = $.map(response.results, function(item) { return new Study(item); });
            self.studies(mappedStudies);
            console.log('loaded studies ' + JSON.stringify(mappedStudies));
        }
    });    
}

// Class to represent a Study
function Study(data) {
   var self = this;
   self.id = data.id;
   self.name = data.text;
}

// Overall Study viewmodel
function StudyViewModel() {
    var self = this;
    self.studies = [];
}

function HeatmapViewModel() {
    var self = this;
    // ordered row/column ids in heatmap
    self.rowIds = ko.observableArray();
    self.colIds = ko.observableArray(); 
}

function TranscriptViewModel() {
    var self = this;
    // currently selected transcript
    self.transcript = ko.observable();
}

function SampleSetViewModel() {
    var self = this;
    // currently selected sample set
    self.sampleSet = ko.observable();
}






var AppModel = Backbone.Model.extend({

	// Instead of generating a new element, bind to the existing skeleton of
	// the App already present in the HTML.
	el: $("#app"),
	
	
});






// Our overall **AppView** is the top-level piece of UI.
var AppView = Backbone.View.extend({

  // Instead of generating a new element, bind to the existing skeleton of
  // the App already present in the HTML.
  el: $("#todoapp"),

  // Our template for the line of statistics at the bottom of the app.
  statsTemplate: _.template($('#stats-template').html()),

  // Delegated events for creating new items, and clearing completed ones.
  events: {
    "keypress #new-todo":  "createOnEnter",
    "click #clear-completed": "clearCompleted",
    "click #toggle-all": "toggleAllComplete"
  },

  // At initialization we bind to the relevant events on the `Todos`
  // collection, when items are added or changed. Kick things off by
  // loading any preexisting todos that might be saved in *localStorage*.
  initialize: function() {

    this.input = this.$("#new-todo");
    this.allCheckbox = this.$("#toggle-all")[0];

    this.listenTo(Todos, 'add', this.addOne);
    this.listenTo(Todos, 'reset', this.addAll);
    this.listenTo(Todos, 'all', this.render);

    this.footer = this.$('footer');
    this.main = $('#main');

    Todos.fetch();
  },

  // Re-rendering the App just means refreshing the statistics -- the rest
  // of the app doesn't change.
  render: function() {
    var done = Todos.done().length;
    var remaining = Todos.remaining().length;

    if (Todos.length) {
      this.main.show();
      this.footer.show();
      this.footer.html(this.statsTemplate({done: done, remaining: remaining}));
    } else {
      this.main.hide();
      this.footer.hide();
    }

    this.allCheckbox.checked = !remaining;
  },

  // Add a single todo item to the list by creating a view for it, and
  // appending its element to the `<ul>`.
  addOne: function(todo) {
    var view = new TodoView({model: todo});
    this.$("#todo-list").append(view.render().el);
  },

  // Add all items in the **Todos** collection at once.
  addAll: function() {
    Todos.each(this.addOne, this);
  },

  // If you hit return in the main input field, create new **Todo** model,
  // persisting it to *localStorage*.
  createOnEnter: function(e) {
    if (e.keyCode != 13) return;
    if (!this.input.val()) return;

    Todos.create({title: this.input.val()});
    this.input.val('');
  },

  // Clear all done todo items, destroying their models.
  clearCompleted: function() {
    _.invoke(Todos.done(), 'destroy');
    return false;
  },

  toggleAllComplete: function () {
    var done = this.allCheckbox.checked;
    Todos.each(function (todo) { todo.save({'done': done}); });
  }

});




$(document).ready(function() {

	$("#test").multiselect({});

    $("#select-sample-set2").multiselect({});
    
    
    $.ajax({
        url: "{{ url_for('json_search_sample_set') }}",
        type: 'post',
        contentType: 'application/json',
        dataType: 'json',
        data: JSON.stringify({ study: 'study4', q: '' }),
        error: function() { callback(); },
        success: function(response) {
        	console.log('got study');
        	// create 
        	d3.select('#select-sample-set2').selectAll('option')
        	   .data(response.results, function(d) { return d._id; })
        	 .enter()
        	   .append('option')
        	   .attr('value', function(d) { return d._id; })
        	   .text(function(d) { return d.name; });
            

        	
        }
    });	
	

});
	
	
	
////////////////////////////////////////////////////
// UI for selecting Study/Sample Set/Transcript
////////////////////////////////////////////////////
var SelectUI = (function () {
	// selectize.js select boxes
	var selectizeStudy;
	var selectizeSampleSet;
	var selectizeTranscript;
    var xhr;
    
    // bound callbacks
    var onAddSampleSet = [];
    var onAddTranscript = [];
    var onChangeStudy = [];

	// Public properties
    var my = {}
    my.studyName = null;
	my.transcriptItems = d3.map();
	my.sampleSetItems = d3.map();
	
    // Properties of ajax/json
    var sampleSetValueField = '_id';
    var transcriptValueField = '_id';
    
	// Events
    my.on = function(event, callback) {
		switch(event) {
		case 'change-study':
			onChangeStudy.push(callback);
			break;
		case 'add-sample-set':
            onAddSampleSet.push(callback);
			break;
		case 'add-transcript':
	        onAddTranscript.push(callback);
			break;
		default:
			console.warn('unrecognized event' + event);
		}
	}
    
    // reenable options
    my.enableSampleSet = function(value) {
    	data = my.sampleSetItems.get(value);
    	my.sampleSetItems.remove(value);
    	selectizeSampleSet.addOption(data);
    }
    my.enableTranscript = function(value) {
    	data = my.transcriptItems.get(value);
    	my.transcriptItems.remove(value);
        selectizeTranscript.addOption(data);
    }
    // disable options
    my.disableSampleSet = function(value) {
        itemData = selectizeSampleSet.options[value];
        my.sampleSetItems.set(value, itemData);
        selectizeSampleSet.removeOption(value);
        selectizeSampleSet.refreshOptions();
    }
    my.disableTranscript = function(value) {
        itemData = selectizeTranscript.options[value];
        my.transcriptItems.set(value, itemData);
        selectizeTranscript.removeOption(value);
        selectizeTranscript.refreshOptions();
    }
	
	// Reset selection
    my.reset = function() {
        // Clear sample set and transcript selections
        selectizeSampleSet.clearOptions();
        selectizeTranscript.clearOptions();
        // Clear data
        delete my.transcriptItems;
        delete my.sampleSetItems;
        // Reset data
        my.studyName = null;
        my.transcriptItems = d3.map();
        my.sampleSetItems = d3.map();
	};
    
	// parses options and skips any found in items d3.map
	function filterOptions(results, valueField, myitems) {
		var newresults = [];
		for (var i=0; i<results.length; i++) {
			if ( myitems.has(results[i][valueField]) ) {
				continue;
			}
			newresults.push(results[i]);
		}
		return newresults;
	}

    // sample set selector
    var $select = $('#select-sample-set').selectize({
        valueField: sampleSetValueField,
        searchField: ['name', 'desc'],
        maxOptions: 1000,
        openOnFocus: true,
        preload: false,
        render: {
            option: function(data, escape) {
                return '<div>' +
                    '<span><strong>' + escape(data.name) + '</strong></span>' +
                    '<br><span>' + escape(data.desc) + '</span>' +
                    '</div>';
            }           
        },
        load: function(query, callback) {
            $.ajax({
                url: "{{ url_for('json_search_sample_set') }}",
                type: 'post',
                contentType: 'application/json',
                dataType: 'json',
                data: JSON.stringify({ study: my.studyName, q: query }),
                error: function() { callback(); },
                success: function(response) {
                    newresults = filterOptions(response.results, sampleSetValueField, my.sampleSetItems);
                    callback(newresults);
                }
            });
        },
        onItemAdd: function(value, $item) {
            // TODO: get data associated with option (hack?)
            itemData = this.options[value];
            for (var i=0; i < onAddSampleSet.length; i++) {
                onAddSampleSet[i](value, itemData);
            }
            this.clear(); // remove all items from select
            this.open();  // reopen the dropdown for quick multi-select
        }
    });
    var selectizeSampleSet = $select[0].selectize;    
    selectizeSampleSet.disable();
    
    // study selector
    var $select = $('#select-study').selectize({
        valueField: 'id',
        labelField: 'text',
        searchField: 'text',
        preload: true,
        maxOptions: 1000,
        load: function(query, callback) {
            $.ajax({
                url: "{{ url_for('request_studies') }}",
                type: 'post',
                contentType: "application/json",
                dataType: 'json',
                data: JSON.stringify({ q: query }),
                error: function() { callback(); },
                success: function(response) {
                    callback(response.results);
                }
            });
        },
        onChange: function(value) {
            if (!value.length) return;
            // Reset data
            my.reset();
            // Set study name
            my.studyName = value;
            // Load sample sets
            selectizeSampleSet.load(function(callback) {
                xhr && xhr.abort();
                xhr = $.ajax({
                    url: "{{ url_for('json_search_sample_set') }}",
                    type: 'post',
                    contentType: 'application/json',
                    dataType: 'json',
                    data: JSON.stringify({ study: my.studyName, q: '' }),
                    error: function() { callback(); },
                    success: function(response) {
                        newresults = filterOptions(response.results, sampleSetValueField, my.sampleSetItems);
                    	callback(newresults);
                    }
                });
            });
            // Enable selection of sample set and transcript
            selectizeSampleSet.enable();
            selectizeTranscript.enable();
            // User callbacks
            for (var i=0; i < onChangeStudy.length; i++) {
                onChangeStudy[i](my.studyName);
            }
        }
    });
    selectizeStudy = $select[0].selectize;

    // transcript searcher
    var $select = $('#select-transcript').selectize({
        valueField: '_id',
        searchField: ['name', 'category', 'locus', 'nearest_gene_names', 
                      'nearest_gene_ids'], 
        maxOptions: 1000,
        preload: false,
        render: {
            option: function(data, escape) {
            	return '<div><span><strong>' + escape(data.name) + '</strong> (' + 
            		   escape(data.gene_id) + ') <em>' + escape(data.category) + '</em></span></br>' + 
            		   '<span>' + escape(data.nearest_gene_names) + '</span></br>' +
            		   '<span>' + escape(data.locus) + '</span></div>';
            }
        },
        load: function(query, callback) {
            if (!query.length) return callback();
            $.ajax({
                url: "{{ url_for('json_search_transcript') }}",
                type: 'post',
                contentType: 'application/json',
                dataType: 'json',
                data: JSON.stringify({ study: my.studyName, q: query }),
                error: function() {
                	console.warning('AJAX search transcript error');
                	callback(); 
                },
                success: function(response) {
                    newresults = filterOptions(response.results, transcriptValueField, my.transcriptItems);
                    callback(newresults);
                }
            });
        },
        onItemAdd: function(value, $item) {
            // TODO: get data associated with option (hack?)
            itemData = this.options[value];
            for (var i=0; i < onAddTranscript.length; i++) {
                onAddTranscript[i](value, itemData);
            }
            this.clear(); // remove all items from select
            this.open();  // reopen the dropdown for quick multi-select
        }
    });
    var selectizeTranscript = $select[0].selectize;
    selectizeTranscript.disable();
    
    return my;
}());

</script>

<script src="{{ url_for('static', filename='js/figue.js') }}"></script>
<script src="{{ url_for('static', filename='js/heatmap.js') }}"></script>

<script>
///////////////////////////////////////////////////////
//D3 heatmap view
///////////////////////////////////////////////////////

// function for rounding floats on tooltips
var roundFunc = d3.format(".3f");

// legend for heatmap
var heatmapLegend = HeatmapLegend({
    width: 1600,
    height: 100,
    margin: { top: 10, right: 600, bottom: 50, left: 60 },
    axisOrient: 'bottom',
    colorDomain: [-20, 0, 20],
    colorRange: ['blue', 'white', 'red']
});

// instance of heatmap
var heatmap = Heatmap({
    // configuration
    rowLabelField: 'name',
    colLabelField: 'name',
    heatmapValueField: 'global_nes',
    url: "{{ url_for('json_request_heatmap_data') }}",
    width: 1600,
    height: 800,
    padding: 5,
    margin: { top: 50, right: 600, bottom: 300, left: 60 },
    colorDefault: "#888888",    
    colorScale: heatmapLegend.getColorScale(), // bind heatmap color scale to legend
    toolTipHtmlFunc: function(d) {
        return "<strong>Global NES:</strong> <span style='color:red'>" + roundFunc(d.value.value) + "</span>";    	
    },
    rowLabelFunc: function(selection, d) {
        var color = 'black';
        switch(d.category) {
          case 'protein': color = '#ff0000'; break;
          case 'ncrna': color = '#ffa500'; break;
          default: color = '#ff00ff'; break;
        }
    	selection.append('tspan')
    	    .style('stroke', 'none')
    	    .style('fill', color)
    	    .text(d.name + ' / ' + d.gene_id + ' / ' + d.category + ' / ' + d.nearest_gene_names + ' / ' + d.locus);
        /*
    	selection.append('tspan')
    	    .text(' (' + d.gene_id + ') ');
    	selection.append('tspan')
            .style('fill', color)
    	    .text(d.category);
    	*/
    }
});

// bind heatmap to selection
d3.select('#chart').call(heatmap.create);
// bind legend to selection
d3.select('#legend').call(heatmapLegend.create);
// bind heatmap to legend so that adding/removing from 
// heatmap changes legend
heatmap.on('change', function() {
    heatmapLegend.update(heatmap.getData());
});
// bind legend to heatmap so that clicking legend changes colors of 
// heatmap points
heatmapLegend.on('change', function() {
	heatmap.recolor();	
});
// when data is added to heatmap remove from select boxes
heatmap.on('add', function(args) {
    for (var i=0; i < args.rows.length; i++) {
        SelectUI.disableTranscript(args.rows[i])
    }
    for (var i=0; i < args.cols.length; i++) {
        SelectUI.disableSampleSet(args.cols[i]);
    }
});
// when data is removed from heatmap add back to select boxes
heatmap.on('remove', function(args) {
	for (var i=0; i < args.rows.length; i++) {
	    SelectUI.enableTranscript(args.rows[i])
	}
    for (var i=0; i < args.cols.length; i++) {
        SelectUI.enableSampleSet(args.cols[i]);
    }
});

// bind user interface to heatmap
SelectUI.on('change-study', function(value) {
    // reset heatmap for new study
    heatmap.clear();
});
SelectUI.on('add-sample-set', function(key, itemData) {
    heatmap.add(SelectUI.studyName, [], [{key: key, value: itemData}]);
});
SelectUI.on('add-transcript', function(key, itemData) {
    heatmap.add(SelectUI.studyName, [{key: key, value: itemData}], []);
});


function svgToBase64String(selection) {
	// selection must be an SVG element
    var html = selection
        .attr('title', 'title')
        .attr('version', 1.1)
        .attr('xmlns', 'http://www.w3.org/2000/svg')
        .node().parentNode.innerHTML;
	return btoa(html);
}

function downloadImage(element, outputFormat) {
    // Extract the data as SVG text string
    var svgXml = (new XMLSerializer).serializeToString(element);    
    // Submit the form to the server.
    // The result will be an attachment file to download.
    var form = document.getElementById("svgform");
    form['output_format'].value = outputFormat;
    form['data'].value = svgXml;
    form.submit();
}

/*
data = svgToBase64String(d3.select('#chart').select('svg'));
d3.select('#sidebar')
    .append('img')
    .attr('src', 'data:image/svg+xml;base64,' + data);
*/

$(document).ready(function() {
    $('#save-pdf').click(function () {
        var el = document.getElementById('chart').getElementsByTagName('svg')[0];
        downloadImage(el, 'pdf');
    });
    $('#save-png').click(function () {
        var el = document.getElementById('chart').getElementsByTagName('svg')[0];
        downloadImage(el, 'png');
    });
	$('#save-svg').click(function () {
		alert('click');
		var el = document.getElementById('chart').getElementsByTagName('svg')[0];
		downloadImage(el, 'svg');
	});
});

</script>

{% endblock %}



